package controllers

import (
	"fly/global"
	"fly/helper"
	"fly/models"
	"fly/req"
	"fly/resp"
	"fly/schema"
	"fly/service"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/duke-git/lancet/v2/slice"
	"net/url"
)

// FlightTaskController 飞行任务
type FlightTaskController struct {
	BaseController
	FlightTaskService        service.FlightTaskService
	SysUserService           service.SysUserService
	SysDictService           service.SysDictService
	SysDeptService           service.SysDeptService
	AircraftService          service.AircraftService
	AirportService           service.AirportService
	AircraftComponentService service.AircraftComponentService
	LifetimeRecordService    service.LifetimeRecordService
}

// Save ...
// @Title 添加或者编辑飞机任务
// @Description 添加或者编辑飞机任务
// @Param token header  string	false "授权Token"
// @Param body body req.FlightTaskSaveReq true "添加或者编辑飞机任务"
// @Success 200 {object} resp.FlightTaskResp
// @router /save [post]
func (c *FlightTaskController) Save() {
	con := req.FlightTaskSaveReq{}
	c.CheckReqErrorAbort(c.BindJSON(&con))
	c.ValidReqParams(&con)
	uid := c.GetReqUserId()
	id, err := c.saveTask(con)
	c.CheckRespErrorAbort(err)
	r := resp.FlightTaskResp{}
	task, err := models.GetFlightTaskById(id)
	err = resp.Copy2TimeResp(&r, task)
	c.CheckRespErrorAbort(err)
	r.CreatorName, err = c.SysUserService.GetUserRealNameById(uid)
	r.UpdaterName = r.CreatorName
	c.CheckRespErrorAbort(err)
	c.Success(r)
}

func (c *FlightTaskController) saveTask(con req.FlightTaskSaveReq) (int64, error) {
	mFlightTask := models.FlightTask{}
	c.CheckRespErrorAbort(helper.CopyDeep(&mFlightTask, con))
	mFlightTask.PlanEnd = helper.Int2TimePoint(con.PlanEnd)
	mFlightTask.PlanStart = helper.Int2TimePoint(con.PlanStart)
	var err error
	id := con.Id
	uid := c.GetReqUserId()
	if con.Id > 0 {
		old, _ := models.GetFlightTaskById(con.Id)
		c.CheckReqErrorAbort(helper.RequireTrue(old != nil, "未找到资源"))
		_ = helper.CopyOut(old, con)
		err = models.UpdateFlightTaskById(old, uid)
		if con.Status == schema.FlightTaskBreakCancel {
			// 故障取消，需要单独保存飞机状态
			_ = c.AircraftService.UpdateAircraftStatusByTaskStatus(schema.FlightTaskBreakCancel, con.AircraftId, uid)
		}
	} else {
		id, err = models.AddFlightTask(&mFlightTask, uid)
	}
	// 保存组件
	aircraft, _ := c.AircraftService.GetSimpleAircraftById(mFlightTask.AircraftId)
	_ = c.AircraftComponentService.SaveOrUpdateComponent(mFlightTask.AircraftId, aircraft.DeptId, 0,
		con.ComponentSaveReq, 0, uid)
	_ = global.DelCache(fmt.Sprintf(service.AircraftCacheSimple, mFlightTask.AircraftId))
	_ = global.DelCache(fmt.Sprintf(service.FlightTaskCacheAircraftKey, mFlightTask.AircraftId))
	_ = global.DelCache(fmt.Sprintf(service.FlightTaskListCacheAircraftKey, mFlightTask.AircraftId))
	return id, err
}

// SaveList ...
// @Title 添加或者编辑飞机任务列表
// @Description 添加或者编辑飞机任务列表
// @Param token header  string	false "授权Token"
// @Param body body []req.FlightTaskSaveReq true "添加或者编辑飞机任务"
// @router /saveList [post]
func (c *FlightTaskController) SaveList() {
	var params []*req.FlightTaskSaveReq
	c.CheckReqErrorAbort(c.BindJSON(&params))
	for _, param := range params {
		c.ValidReqParams(param)
	}
	for _, param := range params {
		_, err := c.saveTask(*param)
		c.CheckRespErrorAbort(err)
	}
	c.Ok()
}

// Recommend ...
// @Title 推荐
// @Description 推荐执行任务飞机
// @Param token header  string	false "授权Token"
// @Param body body []req.FlightTaskRecommendReq true "推荐执行任务参数"
// @Success 200 {object} resp.RecommendAircraftResp
// @router /recommend [post]
func (c *FlightTaskController) Recommend() {
	var params []*req.FlightTaskRecommendReq
	c.CheckReqErrorAbort(c.BindJSON(&params))
	for _, param := range params {
		c.ValidReqParams(param)
	}
	list, err := c.FlightTaskService.RecommendAircraft(params)
	c.CheckRespErrorAbort(err)
	c.Success(list)
}

// Del ...
// @Title 删除飞机任务
// @Description 删除飞机任务，使用逻辑删除
// @Param token header  string	false "授权Token"
// @Param path id int true "飞机任务id"
// @Success 200 {int} "id"
// @router /:id [delete]
func (c *FlightTaskController) Del() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	m, err := models.GetFlightTaskById(id)
	c.CheckReqErrorAbort(err)
	_ = global.DelCache(fmt.Sprintf(service.AircraftCacheSimple, m.AircraftId))
	_ = global.DelCache(fmt.Sprintf(service.FlightTaskCacheAircraftKey, m.AircraftId))
	_ = global.DelCache(fmt.Sprintf(service.FlightTaskListCacheAircraftKey, m.AircraftId))
	c.CheckRespErrorAbort(models.DestroyFlightTask(id, c.GetReqUserId()))
	c.Success(id)
}

// UpdateStatus 更新状态
// @Title UpdateStatus
// @Description 更新状态
// @Param token header  string	false "授权Token"
// @Param path id int true "字典id"
// @Success 200 {int} "id"
// @router /status/:id [put]
func (c *FlightTaskController) UpdateStatus() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	params := req.FlightTaskStatusReq{}
	c.CheckReqErrorAbort(c.BindJSON(&params))
	c.ValidReqParams(&params)
	m, err := models.GetFlightTaskById(id)
	c.CheckAssertAbort(m, "资源不存在")
	c.CheckReqErrorAbort(helper.RequireTrue(m.Status == schema.StatusDefault, "当前任务状态不可更改"))
	c.CheckReqErrorAbort(helper.RequireTrue(params.Status == schema.FlightTaskCancel ||
		params.Status == schema.FlightTaskFinish || params.Status == schema.FlightTaskBreakCancel ||
		params.Status == schema.FlightTaskExecuting || params.Status == schema.FlightTaskInvalid, "任务状态错误"))
	c.CheckRespErrorAbort(c.FlightTaskService.FinishTask(&params, m, c.GetReqUserId()))
	err = c.AircraftService.UpdateAircraftStatusByTaskStatus(params.Status, m.AircraftId, c.GetReqUserId())
	_ = global.DelCache(fmt.Sprintf(service.AircraftCacheSimple, m.AircraftId))
	_ = global.DelCache(fmt.Sprintf(service.FlightTaskCacheAircraftKey, m.AircraftId))
	_ = global.DelCache(fmt.Sprintf(service.FlightTaskListCacheAircraftKey, m.AircraftId))
	c.CheckRespErrorAbort(err)
	c.Ok()
}

// Index ...
// @Title 飞机任务列表
// @Description 飞机任务列表
// @Param token header  string	false "授权Token"
// @Param keywords query  string false "搜索字段"
// @Param pageNum query  int false "当前页"
// @Param pageSize query  int false "每页数量"
// @Param total query  int false "数据总数"
// @Param code query  string false "任务编号"
// @Param aircraftCode query  string false "飞机编号"
// @Param startTime query  int false "录入开始时间"
// @Param endTime query  int false "录入结束时间"
// @Param sceneId query  int false "飞机任务场景类型Id"
// @Success 200 {object} []service.Pagination
// @router / [get]
func (c *FlightTaskController) Index() {
	params, _ := url.ParseQuery(c.Ctx.Request.URL.RawQuery)
	data, pagination := c.FlightTaskService.GetPaginateData(params)
	var taskList []resp.FlightTaskResp
	c.CheckRespErrorAbort(resp.Copy2TimeResp(&taskList, &data))
	for i, task := range data {
		taskList[i].CreatorName, _ = c.SysUserService.GetUserRealNameById(task.Creator)
		taskList[i].UpdaterName, _ = c.SysUserService.GetUserRealNameById(task.Updater)
		taskList[i].TaskTypeName, _ = c.SysDictService.GetDictValueById(task.TaskTypeId)
		taskList[i].TaskSceneName, _ = c.SysDictService.GetDictValueById(task.TaskSceneId)
		taskList[i].TargetAirport, _ = c.AirportService.GetSimpleAirportById(task.TargetAirportId)
		taskList[i].Aircraft, _ = c.AircraftService.GetSimpleAircraftById(task.AircraftId)
	}
	pagination.List = taskList
	c.Success(pagination)
}

// Detail ...
// @Title 飞机任务详情
// @Description 飞机任务详情
// @Param token header  string	false "授权Token"
// @Success 200 {object} resp.FlightTaskResp
// @router /:id [get]
func (c *FlightTaskController) Detail() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	task, err := c.FlightTaskService.GetTaskById(id)
	c.CheckReqErrorAbort(err)
	flightTask := resp.FlightTaskResp{}
	c.CheckRespErrorAbort(resp.Copy2TimeResp(&flightTask, &task))
	flightTask.CreatorName, _ = c.SysUserService.GetUserRealNameById(task.Creator)
	flightTask.UpdaterName, _ = c.SysUserService.GetUserRealNameById(task.Updater)
	flightTask.TaskTypeName, _ = c.SysDictService.GetDictValueById(task.TaskTypeId)
	flightTask.TaskSceneName, _ = c.SysDictService.GetDictValueById(task.TaskSceneId)
	flightTask.TargetAirport, _ = c.AirportService.GetSimpleAirportById(task.TargetAirportId)
	flightTask.Aircraft, _ = c.AircraftService.GetSimpleAircraftById(task.AircraftId)
	records := c.LifetimeRecordService.GetRecordByTaskId(task.Id)
	if len(records) > 0 {
		lifeRecords := slice.Map(records, func(index int, item *models.LifetimeRecord) *resp.LifetimeRecordResp {
			taskResp := resp.LifetimeRecordResp{}
			_ = resp.Copy2TimeResp(&taskResp, item)
			component, _ := c.AircraftComponentService.GetComponentById(item.ComponentId)
			taskResp.ComponentType = component.Type
			taskResp.ComponentName = component.Name
			taskResp.IntervalDuration = component.IntervalDuration
			taskResp.IntervalCount = component.IntervalCount
			taskResp.AdjustTypeName = schema.AdjustMap[item.AdjustType]
			return &taskResp
		})
		flightTask.LifetimeRecords = lifeRecords
	}
	var rels []*models.AircraftComponentRel
	_, err = orm.NewOrm().QueryTable(new(models.AircraftComponentRel)).Filter("aircraft_id", task.AircraftId).All(&rels)
	if err == nil && len(rels) > 0 {
		flightTask.Components = slice.Map(rels, func(index int, item *models.AircraftComponentRel) *resp.AircraftComponentResp {
			componentResp := resp.AircraftComponentResp{}
			component, e := models.GetAircraftComponentById(item.ComponentId)
			if e != nil {
				return nil
			}
			_ = resp.Copy2TimeResp(&componentResp, component)
			componentResp.DeptName, _ = c.SysDictService.GetDictValueById(component.DeptId)
			componentResp.StateName, _ = c.SysDictService.GetDictValueById(component.StateDictId)
			return &componentResp
		})
	}
	c.Success(flightTask)
}
